
Jx.Class = Jx.extend({

	map: null,

	pending: null,

	declaring: false,

	categories: null,

	processors: null,

	callbacks: null,

	shortcuts: null,

	preprocessorsToRemove: null,

	processorPrefix: '$',

	classMapConstructor: null,

	constructor: function(){

		this.map = {};

		this.callbacks = {};

		this.shortcuts = {};

		this.preprocessorsToRemove = [];

		this.classMapConstructor = function(){};

		this.processors = {

			'predefine': {},

			'predeclare': {},

			'postdeclare': {}

		};

		this.pending = [];

		this.categories = {};

		this.$super(arguments);

		this.initialize();

	},

	initialize: function(){

		var J = Jx, o;

		o = this.link('Jx', J);

		J.assign( o, {

			instance: J,

			declared: true,

			aliased: false

		});

		o = this.link('Jx.Class', this);

		J.assign( o, {

			singleton: true,

			declared: true,

			aliased: false

		});

	},

	create: function(name, properties){

		var o = this.parseName(name),

			r;

		if (o){

			o = this.createLinkData(o.path);

			Jx.assign(o.properties,

				o.definition = properties instanceof Object ?

					properties

					:

					{}

			);


			//-- remove process properties
			for(var n, p = o.properties, prefix = this.processorPrefix, toRemove = this.preprocessorsToRemove, l = toRemove.length; l--;){

				if (p.hasOwnProperty(n = prefix+toRemove[l])){

					delete p[n];

				}

			}


			this.process('predefine', o);

			r = o.requires;

			//-- apply required classes
			r.splice(r.length, 0, o.base);

			//-- queue pending class
			this.pending.push( o );

			this.runDeclarations();

		}

	},

	createCategory: function(name, properties){

		properties = Jx.isObject(properties) ?

			properties

			:

			properties;

		properties.$categorized = true;

		return this.create(name, properties);

	},

	createNs: function(name, root){

		var data;

		this.tokenizeNs(name, function(token){

			var o = this.obj;

			if (!(token in o)){

				o[token] = {};

			}

			this.obj = o[token];

		}, data = {

			obj: root || Jx.GLOBAL

		});

		return data.obj;

	},

	createLinkData: function(name){

		var parsed = this.parseName(name),

			data, base;

		if (parsed){

			if (!this.getData(parsed.path)){

				base = function(){};

				base.prototype = new this.classMapConstructor();

				Jx.assign(base.prototype, parsed);

				this.map[name] = new base();

			}

			data = this.resetData(name);

		}

		return data;

	},

	get: function(name, getConstructor){

		var data = this.getData(name, true),

			instance, nil;

		if (data){

			instance = data.instance;

			return getConstructor !== false && data.singleton ?

				instance.constructor

				:

				instance;

		}

		return nil;

	},

	getData: function(name, resolveAlias){

		var map = this.map, nil, o;

		return this.exists(name, false) ?

			(o = map[name]).alias && resolveAlias ?

				map[ o.alias ]

				:

				o

			:

			nil;

	},

	getCategory: function(name){

		var cats = this.categories, nil;

		return Jx.isString(name) && cats.hasOwnProperty(name) ?

			cats[name]

			:

			nil;

	},

	exists: function(name, classExists){

		classExists = classExists !== false;

		var map = this.map, o;

		return Jx.isString(name) && map.hasOwnProperty(name) ?

			!classExists || map[name].declared

			:

			false;

	},

	isDeclared: function(name){

		return this.exists(name, true);

	},

	canDeclareData: function(o){

		//-- check required
		var requires = o.requires;

		for(var cdata, l = requires.length; l--;){

			if (!this.exists(requires[l], true)){

				return false;

			}

		}

		return true;

	},

	setPredefinitions: function(name, fn){

		this.setProcessor('predefine', name, fn);

	},

	setPreprocessor: function(name, fn){

		this.setProcessor('predeclare', name, fn);

	},

	setPostprocessor: function(name, fn){

		this.setProcessor('postdeclare', name, fn);

	},

	setProcessor: function(type, name, fn){

		var toRemove = this.preprocessorsToRemove,

			processors = this.processors,

			collection;

		if (Jx.isString(type) && processors.hasOwnProperty(type)){

			if (Jx.isObject(name)){

				Jx.each(name, function(n, v, o){

					if (o.hasOwnProperty(n)){

						this.Mgr.setProcessor(this.type, n, v);

					}

				}, { Mgr: this, type: type });

			} else if (Jx.isString(name) && name && Jx.isFunction(fn)){

				this.processors[type][name] = fn;

				if (toRemove.indexOf(name) == -1){

					toRemove.push(name);

				}

			}

		}

	},

	setCallback: function(name, fn, scope){

		var callbacks = this.callbacks,

			o = this.parseName(name),

			data, instance, Class;

		if (o && Jx.isFunction(fn)){

			name = o.path;

			if (!callbacks.hasOwnProperty(name)){

				callbacks[name] = [];

			}

			callbacks[name].push({

				fn: fn,

				scope: scope || this

			});

			this.applyDeclareCallbacks(name);

		}

	},

	setCategory: function(name, category){

		if ( Jx.isString(name, true) &&

			Jx.isString(category, true) &&

			name !== category

		){

			//-- use callback
			this.setCallback(name, function(Class, Base, instance){

				this.categories[ this.name ] = instance;

			}, { categories: this.categories, name: category });

		}

	},

	setShortcuts: function(ns, methods){

		var shortcuts = this.shortcuts;

		if (Jx.isString(ns, true) && Jx.isObject(methods)){

			if (!shortcuts.hasOwnProperty(ns)){

				shortcuts[ns] = {};

			}

			Jx.assign(shortcuts[ns], methods);

			//-- try applying shortcuts
			var data =  this.getData(ns);

			if (data && data.instance){

				this.applyShortcuts(ns, data.instance);

			}

		}

	},

	applyShortcuts: function(ns, o){

		var shortcuts = this.shortcuts;

		if (Jx.isString(ns, true) &&

			o &&

			o instanceof Object &&

			shortcuts.hasOwnProperty(ns)

		){

			Jx.assign(o, shortcuts[ns]);

		}

	},

	link: function(name, instance){

		var o = this.parseName(name),

			map = this.map,

			GLOBAL = Jx.GLOBAL,

			created = void(0),

			nsData = void(0),

			update = void(0);

		if (o){

			if (o.ns){

				function APPLY_LINK(token){

					var me = arguments.callee,

						ns = me.ns,

						path = ns ?

							ns+'.'+token

							:

							token,

						data, nsData, nsObject;

					//-- update namespace
					me.ns = path;

					nsData = ns ?

						this.getData(ns)

						:

						null;
					
					nsObject = nsData ?

						nsData.instance

						:

						me.nsObject;

					data = this.getData(path);

					if (!data){

						data = this.createLinkData(path);
						
					}
					
					if (!(token in nsObject)){

						nsObject[ token ] = {};

					}
					
					if (typeof data.instance == 'undefined'){
						
						data.instance = nsObject[token];
						
					}
					
					this.applyShortcuts(data.path, data.instance);
					
					//-- link to ns
					if (nsData){

						nsData.children[ token ] = data;

					}

					//-- update nsObject
					me.nsObject = data.instance;

				}

				//-- create ns link
				APPLY_LINK.ns = '';

				APPLY_LINK.nsObject = GLOBAL;

				this.tokenizeNs(o.ns, APPLY_LINK, this);

				delete APPLY_LINK.ns;

				delete APPLY_LINK.nsObject;

			}

			//-- create link
			name = o.path;

			created = this.getData(name);

			nsData = this.getData(o.ns);

			update = null;

			//-- link map
			if (!created){

				created = this.createLinkData(name);
				
				update = {};
				
			}

			//-- update ns children
			if (nsData){

				nsData.children[o.name] = created;

			}

			if (instance && instance instanceof Object){

				update = instance;

			}

			//-- update instance
			if (update){

				//-- remove children links
				if (created.instance){

					Jx.each(created.children, function(n, v, o){

						if (o.hasOwnProperty(n)){

							delete this[n];

						}

					}, created.instance);

				}

				//-- update ns link
				(nsData ?

					nsData.instance

					:

					GLOBAL

				)[o.name] = created.instance = update;

				//-- update children
				Jx.each(created.children, function(n, v, o){

					if (o.hasOwnProperty(n)){

						this[n] = v.instance;

					}

				}, update);

				//-- update instance shortcuts
				this.applyShortcuts(created.path, created.instance);

			}



		}

		return created;

	},

	resetData: function(name){

		var data = this.getData(name);

		if (data){

			Jx.assign(data, {

				aliases: [],

				base: null,

				definition: null,

				properties: {},

				requires: [],

				children: {},

				declared: false,

				alias: false,

				singleton: false,

				categorized: false,

				categories: [],

				instance: undefined

			});

		}

		return data;

	},

	declare: function(o, p){

		var Base = this.get(o.base, true),

			Class, instance, name, params;

		if (Base){

			o.declared = true;

			Class = Base.extend(o.properties);

			Class.definition = o.definition;

			name = Class.$name = o.path;

			this.process('predeclare', o, [Class, Base]);

			//-- cascade callbacks
			for(var callbacks = Class.$cascadeCallbacks, l = callbacks.length; l--;){

				callbacks[l].apply(this, [Class, Base, o]);

			}

			//-- finalize instance
			instance = Class;

			if (o.singleton){

				params = o.singletonParameters;

				instance = params ?

					Class.apply(null, params)

					:

					Class();

			}

			//-- category class
			if (o.categorized){

				this.categories[ name ] = o.instance = instance;

			//-- public class
			} else {

				this.link( name, instance );

			}

			this.process('postdeclare', o, [Class, Base, instance]);

			this.applyDeclareCallbacks(name);

		}

	},

	applyDeclareCallbacks: function(name){

		var callbacks = this.callbacks,

			data = this.getData(name),

			Class, Base, instance;

		if (this.isDeclared(name) && callbacks.hasOwnProperty(name)){

			instance = data.instance;

			Class = data.singleton ?

				instance.constructor

				:

				instance;

			Base = Class.$base.constructor;

			for(var callback, fns = callbacks[name], l = fns.length; l--; ){

				callback = fns[l];

				//-- remove from callback list
				fns.splice(l, 1);

				callback.fn.call( callback.scope, Class, Base, instance);

				delete callback.fn;

				delete callback.scope;

			}

			delete callbacks[name];

		}

	},

	tokenizeNs: function(name, fn, scope){

		scope = scope || this;

		if (Jx.isString(name)){

			for(var dot, chr, nil, token, anchor = 0, c=0, l=name.length; c<l; c++){

				chr = name.charAt(c);

				dot = chr == '.';

				if (dot || (c+1) == l){

					token = name.substring(anchor, dot ? c : c+1);

				}

				if (token){

					anchor = c+1;

					if (fn.call(scope, token) === false){

						break;

					}

					token = nil;

				}

			}

		}

	},

	parseName: function(name){

		var ret, i, cls, ns, path;

		if (Jx.isString(name)){

			path = name;

			i = name.lastIndexOf('.');

			ns = '';

			if (i != -1){

				ns = name.substring(0, i);

				name = name.substring(i+1, name.length);

			}

			if (name){

				ret = {

					path: path,

					ns: ns,

					name: name

				};

			}

		}

		return ret;

	},

	process: function(subject, node, args){

		var processors = this.processors;

		if (Jx.isString(subject) && processors.hasOwnProperty(subject)){

			Jx.each(processors[subject], function(n, v, o){

				var name = this.Class.processorPrefix+n,

					node = this.node,

					properties, nil;

				if (o.hasOwnProperty(n) &&

					this.J.isFunction(v)

				){

					properties = node.definition;

					v.apply( this.Class,

						this.args.concat([

							name in properties ?

								properties[name]

								:

								nil,

							properties,

							node

						])

					);

				}

			}, {

				J: Jx,

				node: node,

				args: args || [],

				Class: this

			});

		}


	},

	runDeclarations: function(){

		var pending = this.pending;

		if (!this.declaring){

			this.declaring = true;

			for(var data, index, l = pending.length; l--;){

				data = pending[l];

				if (!data.declared && this.canDeclareData(data)){

					pending.splice(l, 1);

					this.declare(data, data.properties);

					//-- reset
					l = pending.length;

				}

			}


			delete this.declaring;

		}

	}

})();

Jx.Class.setPredefinitions({

	'extend': function(base, def, o){

		if (!base || !Jx.isString(base) || base == 'Object'){

			base = 'Jx';

		}

		o.requires.push(

			o.base = base

		);

	},

	'categorized': function(value, def, o){

		o.categorized = !!value;

	},

	'singleton': function(value, def, o){

		o.singletonParameters = Jx.isArray(value) ?

			value

			:

			null;

		o.singleton = !!value;

	},

	'requires': function(value, def, o){

		var requires;

		if (value && Jx.isString(value)){

			value = [value];

		}

		if (Jx.isArray(value)){

			requires = o.requires;

			requires.splice.apply(requires, [requires.length, 0].concat(value));

		}

	},

	'helpers': function(value, def, o){

		if (Jx.isObject(value)){

			Jx.each(value, function(n, v, o){

				if ( o.hasOwnProperty(n) ){

					this.requires.push( v );

				}


			}, o);

		}

	},

	'accessors': function(value, def, o){

		if (!o.actions){

			o.actions = [];

		}

		if (!Jx.isObject(value)){

			value = {};

		}

		o.definedAccessors = {};

		o.accessorNames = [];

		Jx.each(value, function(property, v, o){

			var properties = this.properties,

				actions = this.actions,

				accessors, camelized;

			if ( property && o.hasOwnProperty(property) ){

				this.definedAccessors[ property ] = v;

				this.accessorNames.push(property);

				//-- create action
				var action = 'set' + property.charAt(0).toUpperCase() + property.substring(1, property.length);

				if (actions.indexOf(action) == -1){

					actions.push(action);

				}

			}

		}, o);



	},

	'actions': function(value, def, o){

		var actions = o.actions = o.actions || [];

		if (Jx.isArray(value)){

			for(var action, l = value.length; l--;){

				if (Jx.isString(action = value[l]) && actions.indexOf(action) == -1){

					actions.push(action);

				}

			}

		}

	},

	'shortcuts': function(value, def, o){

		o.shortcuts = [];

		if (Jx.isObject(value)){

			Jx.each(value, function(className, v, o){

				if (o.hasOwnProperty(className) && Jx.isObject(v)){

					var byClassName = {

							name: this.path,

							methods: {}

						};

					Jx.each(v, function(method, fn, o){

						var isString = Jx.isString(fn, true),

							Class = Jx.Class,

							shortcut = fn;

						if (o.hasOwnProperty(method) &&

							(isString || Jx.isFunction(fn))

						){

							if (isString){

								fn = function(){

									var fnObject = arguments.callee,

										instance = Jx.Class.get(fnObject.shortcutFor, false),

										shortcutMethod = fnObject.shortcutMethod;

									return instance && shortcutMethod in instance ?

										instance[shortcutMethod].apply(instance, arguments)

										:

										undefined;

								}

								fn.shortcutFor = this.name;

								fn.shortcutMethod = shortcut;

							}

							this.methods[ method ] = fn;

						}

					}, byClassName);

					Jx.Class.setShortcuts( className, byClassName.methods );

				}

			}, o);

		}

	}

});

Jx.Class.setPreprocessor({

	'inherit': function(Class, Base, value, def, o){

		var baseData = Base.definition || {},

			baseInheritance = baseData.$inherit,

			inheritance = {},

			inherit = false,

			overrides;

		//-- find inheritance from base
		if (Jx.isObject(baseInheritance)){

			Jx.each(baseInheritance, function(n, v, o){

				if (o.hasOwnProperty(n) && Jx.isFunction(v)){

					this[n] = v;

				}

			}, inheritance);

			inherit = true;

		}

		//-- find inheritance from this class
		if (Jx.isArray(value)){

			for(var i, c=0, l = value.length; c < l; c++){

				if (Jx.isString(i = value[c])){

					inheritance[i] = function(){};

				}

			}

			inherit = true;

		} else if (Jx.isObject(value)){

			Jx.each(value, function(n, v, o){

				var str = Jx.isString(v);

				if (o.hasOwnProperty(n)){

					if (Jx.isString(v)){

						v = function(){};

					}

					if (Jx.isFunction(v)){

						this[n] = v;

					} else if (v === false && this.hasOwnProperty(n)){

						delete this[n];

					}

				}

			}, inheritance);

			inherit = true;

		}

		//-- apply inheritance
		if (inherit){

			Jx.each(Class.definition.$inherit = inheritance, function(n, v, o){

				var BaseProto = this.Base,

					ClassProto = this.Class,

					baseValue, classValue, nil;

				if (o.hasOwnProperty(n) && Jx.isFunction(v)){

					baseValue = BaseProto.hasOwnProperty(n) ?

						BaseProto[n]

						:

						nil;

					classValue = ClassProto.hasOwnProperty(n) ?

						ClassProto[n]

						:

						nil;

					if (Jx.isObject(baseValue) && Jx.isObject(classValue)){

						Jx.each(baseValue, function(n, v, o){

							if (o.hasOwnProperty(n)){

								var cv = this.value,

									nil, value, result;


								value = cv.hasOwnProperty(n) ?

									cv[n]

									:

									nil;

								result = this.verifier.call(this.Class, Base, value, v);

								if (result === false){

									delete cv[n];

								} else if (typeof result == 'undefined'){

									cv[n] = typeof value != 'undefined' ?

										value

										:

										v;

								} else {

									cv[n] = result;

								}

							}


						}, {

							Class: Class,

							Base: Base,

							value: classValue,

							verifier: v

						});

					} else if (Jx.isArray(baseValue) && Jx.isArray(classValue)){

						for(var result, cv, bv, index, nil, l = baseValue.length; l--;){

							bv = baseValue[l];

							index = classValue.indexOf(bv);

							cv = index != -1 ?

								bv

								:

								nil;

							result = v.call(this.Class, Base, bv, cv);

							if (result === false){

								if (index != -1){

									classValue.splice(index, 1);

								}

							} else if (typeof result == 'undefined'){

								if (index == -1){

									classValue.unshift(bv);

								}

							} else {

								if ((index = classValue.indexOf(result)) != -1){

									classValue.unshift(result);

								}

							}



						}


					}

					this.overrides[n] = classValue;

				}

			}, {

				Base: Base.prototype,

				Class: Class.prototype,

				overrides: overrides = {}

			});

			Class.override( overrides );

		}

	},

	'cascadeCallback': function(Class, Base, value, def, o){

		var callbacks = Base.$cascadeCallbacks;

		callbacks = Class.$cascadeCallbacks = Jx.isArray(callbacks) ?

			callbacks.slice(0)

			:

			[];

		if (Jx.isFunction(value)){

			callbacks.splice(0, 0, value);

		}

	},

	'accessors': function(Class, Base, value, def, o){

		var access = '$data',

			BaseAccess = access in Base && Jx.isFunction( Base[access] ) ?

				Base[access]

				:

				function(){},

			Access = function(){},

			overrides = {},

			accessors = o.accessorNames,

			properties = o.properties,

			getter, setter, on, camelized,

			fn;

		Jx.assign(Access.prototype = new BaseAccess(), o.definedAccessors);

		Class[access] = Access;

		Access.names = 'names' in BaseAccess ?

			BaseAccess.names.slice(0)

			:

			[];


		for(var name, names = Access.names, l = accessors.length; l--;){

			if (names.indexOf(name = accessors[l]) == -1){

				names.push(name);

				camelized = name.charAt(0).toUpperCase() + name.substring(1, name.length);

				getter = 'get' + camelized;

				setter = 'set' + camelized;

				on = 'onSet' + camelized;

				//-- create final setter callback
				if (!properties.hasOwnProperty(on)){

					fn = properties[ on ] = overrides[ on ] = function(operation, value){

						this.$cache[ arguments.callee.accessorProperty ] = value;

					};

					fn.accessorProperty = name;

				}

				//-- create getter
				if (!properties.hasOwnProperty(getter)){

					fn = overrides[ getter ] = function(value){

						return this.$cache[ arguments.callee.accessorProperty ];

					};

					fn.accessorProperty = name;

				}

				//-- create accessor
				if (!properties.hasOwnProperty(setter)){

					fn = overrides[ name ] = function(){

						return arguments.length ?

							this[ arguments.callee.accessorSetter ].apply(this, arguments)

							:

							this[ arguments.callee.accessorGetter ]();

					};

					fn.accessorGetter = getter;

					fn.accessorSetter = setter;

				}

			}

		}

		Class.override(overrides);

	},

	'actions': function(Class, Base, value, def, o){

		var access = '$actions',

			BaseActions = access in Base ?

				Base[access]

				:

				[],

			base = access in Base && Base[access],

			actions = o.actions,

			overrides = {},

			properties = o.properties,

			name, l, camelized, fn,

			actionCallName, afterActionName, validateActionName;

		if (!Jx.isArray(base)){

			base = [];

		}

		//-- remove predeclared actions
		for(l = actions.length; l--;){

			if (base.indexOf(actions[l]) != -1){

				actions.splice(l, 1);

			}

		}

		for(l = actions.length; l--;){

			name = actions[l];

			if (base.indexOf(name) == -1){

				camelized = name.charAt(0).toUpperCase() + name.substring(1, name.length);

				validateActionName = 'allow'+camelized;

				afterActionName = 'onAfter'+camelized;

				actionCallName = 'on'+camelized;

				if (!properties.hasOwnProperty( actionCallName )){

					overrides[ actionCallName ] = function(){}

				}

				if (!properties.hasOwnProperty( afterActionName )){

					overrides[ afterActionName ] = function(){}

				}

				if (!properties.hasOwnProperty( validateActionName )){

					overrides[ validateActionName ] = function(){}

				}

				if (!properties.hasOwnProperty(name)){

					overrides[ name ] = fn = function(){

						var operation = {

								property: arguments.callee.actionName,

								arguments: Array.prototype.slice.call(arguments, 0),

								returnValue: this

							},

							o = arguments.callee,

							args = [operation].concat(operation.arguments);

						if (this[ o.actionValidator ].apply(this, args) !== false){

							this[ o.actionCall ].apply(this, args);

							this[ o.actionAfterCall ].apply(this, args);

						}

						return operation.returnValue;

					}

					fn.actionValidator = validateActionName;

					fn.actionAfterCall = afterActionName;

					fn.actionCall = actionCallName;

					fn.actionName = name;

				}

			}

		}

		Class.override(overrides);

		Class[access] = base.concat(actions);

	},

	'preprocess': function(Class, Base, value, def, o){

		var properties = o.properties,

			overrides;

		if (Jx.isFunction(value)){

			overrides = value.call(Base, properties);

			if (Jx.isObject(overrides)){

				Jx.assign(properties, overrides);

			}

		}

	},

	'static': function(Class, Base, value, def, o){

		var base = Base.$static,

			BaseStatic = base ?

				base.constructor

				:

				Jx,

			Static = BaseStatic.extend(

				Jx.isObject(value) ?

					value

					:

					{}

			);

		var shortcuts = {};

		Jx.each( Class.$static = Static(Class), function(n, v, o){

			var shortcuts = this.shortcuts,

				shortcut;

			if (!Jx.prototype.hasOwnProperty(n)){

				if (Jx.isFunction(v)){

					shortcuts[n] = shortcut = function(){

						var o = arguments.callee;

						return o.staticMethod.apply( o.staticClass, arguments);

					};

					shortcut.staticClass = this.Class;

					shortcut.staticMethod = v;

					v = shortcut;

				}

				shortcuts[n] = v;

			}

		}, {

			Class: Class,

			shortcuts: shortcuts

		});

		this.setShortcuts(o.path, shortcuts);

	},

	'helpers': function(Class, Base, value, def, o){

		if (Jx.isObject(value)){

			//-- set helpers
			Jx.each(value, function(n, v, o){

				var instance;

				if (o.hasOwnProperty(n) &&

					(instance = this.Mgr.get( v, false ))

				){

					this.Class.prototype[ '$'+n ] = instance;

				}


			}, { Mgr: this, Class: Class });

		}

	},

	'category': function(Class, Base, value, def, o){

		var categories = o.categories,

			name = o.path;

		if (!Jx.isArray(value)){

			value = Jx.isString(value) ?

				[value]

				:

				[];

		}

		for(var data, l = value.length; l--; ){

			data = this.createLinkData( value[l] );

			if (data){

				categories.unshift(data);

			}

		}

	}



});

Jx.Class.setPostprocessor({

	'postprocess': function(Class, Base, Instance, value, def, o){

		var overrides;

		if (Jx.isFunction(value)){

			overrides = value.call(Instance, Base, Class, Instance);

			if (Jx.isObject(overrides)){

				Class.override(overrides);

			}

		}

	},

	'category': function(Class, Base, Instance, value, def, o){

		var categories = o.categories,

			ns = this.categories;

		for(var data, l = categories.length; l--;){

			data = categories[l];

			Jx.each(o, function(n, v, o){

				if (o.hasOwnProperty(n)){

					this[n] = v;

				}

			}, data);

			//-- set instance
			data.instance = ns[ data.path ] = Instance;

		}

	},

	'callback': function(Class, Base, Instance, value, def, o){

		var callbacks = this.callbacks,

			name = Class.$name;

		//-- manual setup of callback
		if (Jx.isFunction(value)){

			if (name in callbacks){

				callbacks[name].unshift({

					fn: value,

					scope: this

				});

			} else {

				this.setCallback(name, value);

			}




		}

	}

});

Jx.assign(Jx, {

	emptyFn: new Function(),

	isClass: function(Class, SuperClass){

		var J = Jx;

		if (J.isString(Class)){

			Class = J.Class.get(Class, true);

		}

		if (!J.isFunction(SuperClass)){

			if (J.isString(SuperClass)){

				SuperClass = J.Class.get(SuperClass, true) || J.emptyFn;

			} else if (SuperClass){

				SuperClass = J.emptyFn;

			}

		}

		return J.isFunction(Class) &&

			( !SuperClass || Class.prototype instanceof SuperClass || Class === SuperClass );

	},

	instanceOf: function(o, Class){

		if (!Jx.isFunction(Class)){

			Class = Jx.Class.get(Class, true);

		}

		return !!Class && o instanceof Class;

	},

	declare: function(path, properties){

		Jx.Class.create(path, properties);

	},

	categorize: function(path, properties){

		Jx.Class.createCategory(path, properties);

	},

	instantiate: function(path, args){

		var Class = Jx.Class.get(path, true), nil;

		return Jx.isFunction(Class) ?

			Class.apply(null, args || [])

			:

			nil;

	},

	onDeclare: function(path, fn, scope){

		Jx.Class.setCallback(path, fn, scope);


	},

	isSingleton: function(path){

		var data = Jx.Class.getData(path);

		return !!data && data.singleton;

	},

	classExists: function(path){

		return Jx.Class.exists(path);

	},

	getConstructor: function(path){

		return Jx.Class.get(path, true);

	},

	getClass: function(path){

		return Jx.Class.get(path, false);

	},

	ns: function(ns){

		var created = undefined,

			returnOne = true;

		if (!Jx.isArray(ns)){

			ns = Array.prototype.slice.call(arguments, 0);

			returnOne = ns.length == 1;

		}

		for(var path, C = Jx.Class, l = ns.length; l--;){

			if (Jx.isString(path = ns[l], true)){

				if (!created){

					created = [];

				}

				created.push(

					C.createNs(path)

				);

			}

		}

		return returnOne ?

			created && created[0]

			:

			created;

	}

});

//-- declare undeclared classes
(function(J, temps){

	var l, o, args, method;

	for(var l = temps.length; l--;){

		args = temps[l];

		if ((method = args.method) in J){

			J[ method ].apply(J, args);

		}

	}

	delete Jx.temporaryClassMethodCalls;

})(Jx, Jx.temporaryClassMethodCalls);
